package com.ruoyi.datastatistics.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.date.DateUtil;
import com.ruoyi.basedata.domain.UserAccount;
import com.ruoyi.basedata.domain.UsersXb;
import com.ruoyi.basedata.mapper.UserAccountMapper;
import com.ruoyi.basedata.mapper.UsersXbMapper;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.datastatistics.domain.Bill;
import com.ruoyi.datastatistics.domain.BillDetail;
import com.ruoyi.datastatistics.domain.UserPrePayment;
import com.ruoyi.datastatistics.mapper.BillDetailMapper;
import com.ruoyi.datastatistics.mapper.BillMapper;
import com.ruoyi.datastatistics.service.IUserPrePaymentService;
import com.ruoyi.system.mapper.SysDictDataMapper;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.datastatistics.mapper.UserPrePaymentMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
/**
 * 预存缴费记录Service业务层处理
 * 
 * @author gdqt
 * @date 2025-06-27
 */
@Service
public class UserPrePaymentServiceImpl extends ServiceImpl<UserPrePaymentMapper, UserPrePayment> implements IUserPrePaymentService
{
    @Autowired
    private UserPrePaymentMapper userPrePaymentMapper;
    @Autowired
    private UserAccountMapper userAccountMapper;

    @Autowired
    private BillMapper billMapper;

    @Autowired
    private BillDetailMapper billDetailMapper;

    @Autowired
    private UsersXbMapper usersXbMapper;
    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    /**
     * 查询预存缴费记录
     * 
     * @param id 预存缴费记录主键
     * @return 预存缴费记录
     */
    @Override
    public UserPrePayment selectUserPrePaymentById(Long id)
    {

        return userPrePaymentMapper.selectById(id);
    }

    /**
     * 查询预存缴费记录列表
     * 
     * @param userPrePayment 预存缴费记录
     * @return 预存缴费记录
     */
    @Override
    public List<UserPrePayment> selectUserPrePaymentList(UserPrePayment userPrePayment)
    {
        LambdaQueryWrapper<UserPrePayment> queryWrapper = new LambdaQueryWrapper<>();
        if(!StringUtils.isEmpty(userPrePayment.getUserId())){
            queryWrapper.eq(UserPrePayment::getUserId,userPrePayment.getUserId());
        }
        if(!StringUtils.isEmpty(userPrePayment.getTicketType())){
            queryWrapper.eq(UserPrePayment::getTicketType,userPrePayment.getTicketType());
        }
        if(!StringUtils.isEmpty(userPrePayment.getTickerNo())){
            queryWrapper.eq(UserPrePayment::getTickerNo,userPrePayment.getTickerNo());
        }
        if(!StringUtils.isEmpty(userPrePayment.getCollectWay())){
            queryWrapper.eq(UserPrePayment::getCollectWay,userPrePayment.getCollectWay());
        }

        if(!StringUtils.isEmpty(userPrePayment.getCheckMonth())){
            queryWrapper.eq(UserPrePayment::getCheckMonth,userPrePayment.getCheckMonth());
        }
        if(!StringUtils.isEmpty(userPrePayment.getPayType())){
            queryWrapper.eq(UserPrePayment::getPayType,userPrePayment.getPayType());
        }
        if(userPrePayment.getTicketReceiveStatus() != null){
            queryWrapper.eq(UserPrePayment::getTicketReceiveStatus,userPrePayment.getTicketReceiveStatus());
        }
        if(userPrePayment.getPrintStatus() != null){
            queryWrapper.eq(UserPrePayment::getPrintStatus,userPrePayment.getPrintStatus());
        }
        if(userPrePayment.getPayStatus() != null){
            queryWrapper.eq(UserPrePayment::getPayStatus,userPrePayment.getPayStatus());
        }
        if(!StringUtils.isEmpty(userPrePayment.getPayMark())){
            queryWrapper.eq(UserPrePayment::getPayMark,userPrePayment.getPayMark());
        }
        if(!StringUtils.isEmpty(userPrePayment.getCreatedBy())){
            queryWrapper.eq(UserPrePayment::getCreatedBy,userPrePayment.getCreatedBy());
        }
        if(userPrePayment.getCreatedTime() != null){
            queryWrapper.eq(UserPrePayment::getCreatedTime,userPrePayment.getCreatedTime());
        }
        return userPrePaymentMapper.selectList(queryWrapper);
    }

    /**
     * 新增预存缴费记录
     * 
     * @param userPrePayment 预存缴费记录
     * @return 结果
     */
    @Override
    @Transactional
    public int insertUserPrePayment(UserPrePayment userPrePayment)
    {
        if(userPrePayment != null && StringUtils.isNotEmpty(userPrePayment.getUserId())){

            String currentUserId = String.valueOf(SecurityUtils.getUserId());
            //上个月
            String lastMonth = DateUtil.lastMonth().toString("yyyy-MM");
            String userId = userPrePayment.getUserId();
            double payMoney = userPrePayment.getPayMoney().doubleValue();

            //查询系统取整方式 实缴sj，向上取整xsqz，向下取整xxqz
            String payRaoundValue = "sj";
            List<SysDictData> dictDataList = sysDictDataMapper.selectDictDataByType("pay_round_type");
            if (!dictDataList.isEmpty()){
                payRaoundValue = dictDataList.get(0).getDictValue();
            }
            //查找用户基础信息
            UsersXb usersXb = usersXbMapper.selectOne(new LambdaQueryWrapper<UsersXb>().eq(UsersXb::getUserId,userId).eq(UsersXb::getUserMark,1));
            if(usersXb == null){
                //用户可能已经离场，直接返回
                return 0;
            }
            //是否为预存
            int isPayment = usersXb.getIsPrepayment() == null ? 0 : usersXb.getIsPrepayment();

            //1.查找上次预存缴费记录
//            UserPrePayment lastPrePayment = null;
//            List<UserPrePayment> userPrePaymentList = userPrePaymentMapper.selectList(new LambdaQueryWrapper<UserPrePayment>().eq(UserPrePayment::getUserId,userId).orderByDesc(UserPrePayment::getId));
//            if(!userPrePaymentList.isEmpty()){
//                lastPrePayment = userPrePaymentList.get(0);
//            }
//            userPrePayment.setLastMoney(lastPrePayment != null ? lastPrePayment.getCurrentMoney() : BigDecimal.valueOf(0d));
            //1.查找用户账户信息
            UserAccount userAccount = userAccountMapper.selectOne(new LambdaQueryWrapper<UserAccount>().eq(UserAccount::getUserId,userId));
            userPrePayment.setLastMoney(userAccount.getAvailableBalance());
            //预存
            if(isPayment == 0){
                userPrePayment.setCheckMoney(BigDecimal.valueOf(0d));
                userPrePayment.setCurrentMoney(BigDecimal.valueOf(payMoney + userPrePayment.getLastMoney().doubleValue()));
                userPrePayment.setPayStatus(1);
                userPrePayment.setPayType("1");
                userPrePayment.setCreatedTime(new Date());
                userPrePayment.setCreatedBy(currentUserId);
                //2.处理本次预存缴费记录
                userPrePaymentMapper.insert(userPrePayment);
            }else {
                //非预存
                userPrePayment.setCurrentMoney(BigDecimal.valueOf(payMoney + userPrePayment.getLastMoney().doubleValue()));
            }

            //查找开账记录中未核销的记录-总
            List<Bill> billList = billMapper.selectList(new LambdaQueryWrapper<Bill>().eq(Bill::getUserId,userId).eq(Bill::getStatus,0).orderByAsc(Bill::getReadDate).orderByDesc(Bill::getUsageType));
            //查找开账记录详情中未核销的记录-详情
            List<BillDetail> billDetailList = billDetailMapper.selectList(new LambdaQueryWrapper<BillDetail>().eq(BillDetail::getUserId,userId).eq(BillDetail::getStatus,0));

            Map<String,List<BillDetail>> readDateDetailMap = billDetailList.stream().collect(Collectors.groupingBy(BillDetail::getReadDate));
            //当前结余
            double currentMoney = userPrePayment.getCurrentMoney().doubleValue();
            //3.检查是否有未核销
            if(!billList.isEmpty()){
                double totalArrear = 0d;//账户欠费合计
                double monthArrear = 0d;//账户月结欠费
                double latefee = 0d;//账户违约金
                //所有欠费单的合计金额，为了非预存用户计算
                double allBillMoney = billList.stream().mapToDouble(item-> item.getTotalPrice().doubleValue()+item.getLateFee().doubleValue()).sum();
                //循环
                for(int i=0;i<billList.size();i++){
                    Bill bill = billList.get(i);
                    double totalPrice = bill.getTotalPrice().doubleValue();
                    double billLatefee = bill.getLateFee().doubleValue();
                    double checkMoney = totalPrice + billLatefee;
                    String month = bill.getReadDate();
                    if(isPayment == 0){
                        //当前结余大于用量总费用，则进行缴费
                        if(currentMoney >= checkMoney){
                            UserPrePayment temp = new UserPrePayment();
                            temp.setUsageType(bill.getUsageType());
                            temp.setUserId(userId);
                            temp.setCollectWay("1");//余额支付
                            temp.setCheckMonth(month);
                            temp.setLastMoney(BigDecimal.valueOf(currentMoney));
                            temp.setPayMoney(BigDecimal.valueOf(0));
                            temp.setCurrentMoney(BigDecimal.valueOf(currentMoney - checkMoney));
                            temp.setCheckMoney(BigDecimal.valueOf(checkMoney));
                            temp.setPayType("2");//核销
                            temp.setPayStatus(1);
                            temp.setCreatedTime(new Date());
                            temp.setCreatedBy(currentUserId);
                            userPrePaymentMapper.insert(temp);
                            //更新开账记录以及详情
                            bill.setStatus(1);
                            billMapper.updateById(bill);
                            //查到开账详情记录里指定月份的记录
                            if(readDateDetailMap.containsKey(month)){
                                BillDetail billDetail = new BillDetail();
                                billDetail.setStatus(1);
                                List<BillDetail> billDetailList1 = readDateDetailMap.get(month);
                                List<Long> ids = billDetailList1.stream().map(BillDetail::getId).collect(Collectors.toList());
                                billDetailMapper.update(billDetail, new LambdaQueryWrapper<BillDetail>().in(BillDetail::getId,ids));
                            }
                            //最新结余
                            currentMoney -= checkMoney;
                        }else {
                            totalArrear += totalPrice;
                            latefee += billLatefee;
                            if(month.equals(lastMonth)){
                                monthArrear = totalPrice + billLatefee;
                            }
                        }
                    }else {
                        //非预存，只有当存的钱大于等于欠费的，才给核销
                        if(currentMoney>=allBillMoney){
                            double changeMoney = 0;
                            if(billList.size()-1 == i){//最后一个记录，存找零
                                if("sj".equals(payRaoundValue)){//实缴
                                    changeMoney = currentMoney - allBillMoney;
                                    currentMoney = 0;
                                } else if ("xsqz".equals(payRaoundValue)) {//向上取整
                                    changeMoney = currentMoney - Math.ceil(allBillMoney);
                                    currentMoney = Math.ceil(allBillMoney) - allBillMoney;
                                } else if ("xxqz".equals(payRaoundValue)) {//向下取整
                                    changeMoney = currentMoney - Math.floor(allBillMoney);
                                    currentMoney = Math.floor(allBillMoney) - allBillMoney;
                                }
                            }
                            UserPrePayment temp = new UserPrePayment();
                            temp.setUsageType(bill.getUsageType());
                            temp.setUserId(userId);
                            temp.setCollectWay("2");//余额支付
                            temp.setCheckMonth(month);
                            temp.setLastMoney(BigDecimal.valueOf(0));
                            temp.setPayMoney(BigDecimal.valueOf(checkMoney));
                            temp.setCurrentMoney(BigDecimal.valueOf(0));
                            temp.setCheckMoney(BigDecimal.valueOf(checkMoney));
                            temp.setChangeMoney(BigDecimal.valueOf(changeMoney));
                            temp.setPayType("2");//核销
                            temp.setPayStatus(1);
                            temp.setCreatedTime(new Date());
                            temp.setCreatedBy(currentUserId);
                            userPrePaymentMapper.insert(temp);
                            //更新开账记录以及详情
                            bill.setStatus(1);
                            billMapper.updateById(bill);
                            //查到开账详情记录里指定月份的记录
                            if(readDateDetailMap.containsKey(month)){
                                BillDetail billDetail = new BillDetail();
                                billDetail.setStatus(1);
                                List<BillDetail> billDetailList1 = readDateDetailMap.get(month);
                                List<Long> ids = billDetailList1.stream().map(BillDetail::getId).collect(Collectors.toList());
                                billDetailMapper.update(billDetail, new LambdaQueryWrapper<BillDetail>().in(BillDetail::getId,ids));
                            }
                        }else {
                            return -1;
                        }
                    }
                }
                //非预存
                if(isPayment == 1){
//                    currentMoney = 0;
                    monthArrear = 0;
                    latefee = 0;
                    totalArrear = 0;
                }
                //更新账户信息
                userAccount.setTotalArrear(BigDecimal.valueOf(totalArrear));
                userAccount.setLateFee(BigDecimal.valueOf(latefee));
                userAccount.setMonthArrear(BigDecimal.valueOf(monthArrear));
                userAccount.setSettleBalance(BigDecimal.valueOf(currentMoney));
                userAccount.setAvailableBalance(BigDecimal.valueOf(currentMoney));
                userAccount.setUpdatedTime(new Date());
                userAccountMapper.updateById(userAccount);
            }else {
                if(isPayment == 0){
                    //没有未核销，则直接更新用户账户信息
                    userAccount.setSettleBalance(BigDecimal.valueOf(userAccount.getSettleBalance().doubleValue()+currentMoney));
                    userAccount.setAvailableBalance(BigDecimal.valueOf(userAccount.getAvailableBalance().doubleValue()+currentMoney));
                    userAccount.setUpdatedTime(new Date());
                    userAccountMapper.updateById(userAccount);
                }
            }
            return 1;
        }
        return 0;
    }

    /**
     * 修改预存缴费记录
     * 
     * @param userPrePayment 预存缴费记录
     * @return 结果
     */
    @Override
    public int updateUserPrePayment(UserPrePayment userPrePayment)
    {
        return userPrePaymentMapper.updateById(userPrePayment);
    }

    /**
     * 批量删除预存缴费记录
     * 
     * @param ids 需要删除的预存缴费记录主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteUserPrePaymentByIds(Long[] ids)
    {
        return userPrePaymentMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除预存缴费记录信息
     * 
     * @param id 预存缴费记录主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteUserPrePaymentById(Long id)
    {
        return userPrePaymentMapper.deleteById(id);
    }

    @Override
    public List<UserPrePayment> getPrePaymentList(String userId) {
        if(StringUtils.isEmpty(userId)){
            return Collections.emptyList();
        }
        return userPrePaymentMapper.getPrePaymentList(userId);
    }

    @Override
    public Map<String, Object> getPaySummaryToday(String userId) {
        Map<String,Object> resMap = new HashMap<>();
        //pay1为余额支付
        resMap.put("pay2",0);
        resMap.put("pay3",0);
        resMap.put("pay4",0);
        resMap.put("total",0);
        resMap.put("count",0);
        Date startDate = DateUtil.beginOfDay(new Date());
        Date endDate = DateUtil.endOfDay(new Date());
        List<UserPrePayment> list = userPrePaymentMapper.selectList(new LambdaQueryWrapper<UserPrePayment>().eq(UserPrePayment::getUserId,userId)
                        .ne(UserPrePayment::getCollectWay,"1").ge(UserPrePayment::getCreatedTime,startDate).le(UserPrePayment::getCreatedTime,endDate)
                        .eq(UserPrePayment::getPayStatus,1));
        if(!list.isEmpty()){
            //收款方式分组
            Map<String,List<UserPrePayment>> collectWayMap = list.stream().collect(Collectors.groupingBy(UserPrePayment::getCollectWay));
            //现金收费
            if(collectWayMap.containsKey("2")){
                double v = collectWayMap.get("2").stream().mapToDouble(item->item.getPayMoney().doubleValue()).sum();
                resMap.put("pay2",v);
            }
            //转账收费
            if(collectWayMap.containsKey("3")){
                double v = collectWayMap.get("3").stream().mapToDouble(item->item.getPayMoney().doubleValue()).sum();
                resMap.put("pay3",v);
            }
            //在线收费
            if(collectWayMap.containsKey("4")){
                double v = collectWayMap.get("4").stream().mapToDouble(item->item.getPayMoney().doubleValue()).sum();
                resMap.put("pay4",v);
            }
            //收费合计
            resMap.put("total",list.stream().mapToDouble(item->item.getPayMoney().doubleValue()).sum());
            //收费笔数
            resMap.put("count",list.size());
        }
        return resMap;
    }

    /**
    * @Description: 撤销预存
    * @date: 2025/7/2 13:59
    * @author: zt
    */
    @Override
    @Transactional
    public int revokedPrePayment(Long id) {
        //根据预存记录所在ID，进行撤销预存操作，只有最后一条预存记录可撤销
        if (id != null) {
            UserPrePayment userPrePayment = userPrePaymentMapper.selectById(id);
            double payMoney = userPrePayment.getPayMoney().doubleValue();
            userPrePayment.setPayStatus(2);
            userPrePaymentMapper.updateById(userPrePayment);
            //获取用户账户信息
            UserAccount userAccount = userAccountMapper.selectOne(new LambdaQueryWrapper<UserAccount>().eq(UserAccount::getUserId,userPrePayment.getUserId()));
            userAccount.setAvailableBalance(BigDecimal.valueOf(userAccount.getAvailableBalance().doubleValue() - payMoney));
            userAccount.setSettleBalance(BigDecimal.valueOf(userAccount.getSettleBalance().doubleValue() - payMoney));
            userAccountMapper.updateById(userAccount);
            return 1;
        }
        return 0;
    }

    @Override
    public void payBill() {
        //上个月
        String lastMonth = DateUtil.lastMonth().toString("yyyy-MM");
        //查找所有用户账户信息
        List<UserAccount> userAccountList = userAccountMapper.selectList(new LambdaQueryWrapper<>());
        //查找开账记录中未核销的记录-总
        List<Bill> billList = billMapper.selectList(new LambdaQueryWrapper<Bill>().eq(Bill::getStatus,0).orderByAsc(Bill::getReadDate).orderByDesc(Bill::getUsageType));
        Map<String,List<Bill>> userBillMap = billList.stream().collect(Collectors.groupingBy(Bill::getUserId));
        //查找开账记录详情中未核销的记录-详情
        List<BillDetail> billDetailList = billDetailMapper.selectList(new LambdaQueryWrapper<BillDetail>().eq(BillDetail::getStatus,0));
        Map<String,List<BillDetail>> userBillDetailMap = billDetailList.stream().collect(Collectors.groupingBy(BillDetail::getUserId));
        //循环用户
        for (UserAccount userAccount : userAccountList) {
            String userId = userAccount.getUserId();
            UsersXb usersXb = usersXbMapper.selectOne(new LambdaQueryWrapper<UsersXb>().eq(UsersXb::getUserId,userId).eq(UsersXb::getUserMark,1));
            if(usersXb == null){
                //用户可能已经离场，跳到下个循环
                continue;
            }
            //是否为预存
            int isPayment = usersXb.getIsPrepayment() == null ? 0 : usersXb.getIsPrepayment();
            if(isPayment == 1){//非预存，跳到下个循环
                continue;
            }
            double currentMoney = userAccount.getAvailableBalance().doubleValue();

            if(userBillMap.containsKey(userId)){
                List<Bill> bills = userBillMap.get(userId);
                List<BillDetail> billDetails = userBillDetailMap.getOrDefault(userId, null);
                Map<String,List<BillDetail>> readDateDetailMap = billDetails == null ? null : billDetails.stream().collect(Collectors.groupingBy(BillDetail::getReadDate));
                double totalArrear = 0d;//账户欠费合计
                double monthArrear = 0d;//账户月结欠费
                double latefee = 0d;//账户违约金
                for(Bill bill : bills){
                    double totalPrice = bill.getTotalPrice().doubleValue();
                    double billLatefee = bill.getLateFee().doubleValue();
                    double checkMoney = totalPrice + billLatefee;
                    String month = bill.getReadDate();
                    //当前结余大于用量总费用，则进行缴费
                    if(currentMoney >= checkMoney){
                        UserPrePayment temp = new UserPrePayment();
                        temp.setUsageType(bill.getUsageType());
                        temp.setUserId(userId);
                        temp.setCollectWay("1");//余额支付
                        temp.setCheckMonth(month);
                        temp.setLastMoney(BigDecimal.valueOf(currentMoney));
                        temp.setPayMoney(BigDecimal.valueOf(0));
                        temp.setCurrentMoney(BigDecimal.valueOf(currentMoney - checkMoney));
                        temp.setCheckMoney(BigDecimal.valueOf(checkMoney));
                        temp.setPayType("2");//核销
                        temp.setPayStatus(1);
                        temp.setCreatedTime(new Date());
                        temp.setCreatedBy("1");
                        userPrePaymentMapper.insert(temp);
                        //更新开账记录以及详情
                        bill.setStatus(1);
                        billMapper.updateById(bill);
                        //查到开账详情记录里指定月份的记录
                        if(readDateDetailMap != null && readDateDetailMap.containsKey(month)){
                            BillDetail billDetail = new BillDetail();
                            billDetail.setStatus(1);
                            List<BillDetail> billDetailList1 = readDateDetailMap.get(month);
                            List<Long> ids = billDetailList1.stream().map(BillDetail::getId).collect(Collectors.toList());
                            billDetailMapper.update(billDetail, new LambdaQueryWrapper<BillDetail>().in(BillDetail::getId,ids));
                        }
                        //最新结余
                        currentMoney -= checkMoney;
                    }else {
                        totalArrear += totalPrice;
                        latefee += billLatefee;
                        if(month.equals(lastMonth)){
                            monthArrear = totalPrice + billLatefee;
                        }
                    }
                }
                //更新账户信息
                userAccount.setTotalArrear(BigDecimal.valueOf(totalArrear));
                userAccount.setLateFee(BigDecimal.valueOf(latefee));
                userAccount.setMonthArrear(BigDecimal.valueOf(monthArrear));
                userAccount.setSettleBalance(BigDecimal.valueOf(currentMoney));
                userAccount.setAvailableBalance(BigDecimal.valueOf(currentMoney));
                userAccount.setUpdatedTime(new Date());
                userAccountMapper.updateById(userAccount);
            }
        }
    }
}
